#include <GL/gl.h>
#include <GL/glu.h>
#include "SDL.h"

#include <algorithm>
#include <iostream>

#include "asserts.hpp"
#include "filesystem.hpp"
#include "flags.hpp"
#include "foreach.hpp"
#include "font.hpp"
#include "framed_gui_element.hpp"
#include "frame_rate_handler.hpp"
#include "gamemap.hpp"
#include "player.hpp"
#include "raster.hpp"
#include "scenario.hpp"
#include "scenario_complete_screen.hpp"
#include "scenario_setup_screen.hpp"
#include "terrain.hpp"
#include "texture.hpp"
#include "wm.hpp"
#include "wml_node.hpp"
#include "wml_parser.hpp"
#include "wml_utils.hpp"

SDL_Window* g_main_window;

void play_game()
{
	std::string scenario_id = flags::get("scenario", "scenario1");

	game::ScenarioCarryoverState state;
	state.gold = 100;
	state.experience = 0;

	for(;;) {
		game::scenario_ptr scenario(game::scenario::get(scenario_id));

		ASSERT_GT(scenario->players().size(), 0);

		//if the player doesn't have any commanders and the scenario doesn't
		//list commanders for the player, we must be debugging, so load
		//the list of debug commanders.
		if(scenario->players().front()->commanders().empty() && state.commanders.empty()) {
			wml::node_ptr node(wml::parse_wml_from_file("debug_commanders.cfg"));
			FOREACH_WML_CHILD(commander_node, node, "commander") {
				state.commanders.push_back(game::commander_unit_ptr(new game::commander_unit(*scenario->players().front(), commander_node)));
			}
		}

		//set up the scenario by placing commanders in position.
		foreach(game::commander_unit_ptr& cmd, state.commanders) {
			if(scenario->add_player_commander(scenario->players().front(), cmd)) {
				cmd = game::commander_unit_ptr();
			} else {
				ASSERT_LOG(false, "Could not place commander in position");
			}
		}

		game::scenario_setup_screen setup_screen(*scenario, state);
		setup_screen.show_modal();

		state.commanders.erase(std::remove(state.commanders.begin(), state.commanders.end(), game::commander_unit_ptr()), state.commanders.end());

		scenario->play();

		if(scenario->result() && scenario->result()->outcome == "victory") {
			scenario_id = scenario->result()->next_scenario;
		} else {
			return;
		}

		game::scenario_complete_screen complete_screen(*scenario, state);

		frame_rate_handler fps;

		while(!complete_screen.done()) {
				complete_screen.process();
				graphics::prepare_raster();
				complete_screen.draw();
				wm::swap_buffers();
				fps.next_frame();
		}

		complete_screen.show_modal();

		//move the player's commanders back into the carry over state.
		ASSERT_GT(scenario->players().size(), 0);
		foreach(game::commander_unit_ptr cmd, scenario->players().front()->commanders()) {
			cmd->clear_soldiers();
			state.commanders.push_back(cmd);
		}
	}
}

int main(int argc, char** argv)
{
	srand(time(NULL));

	flags::init(argv);

	const int screen_width = flags::get_int("width", 1024);
	const int screen_height = flags::get_int("height", 768);
	const bool fullscreen = false;
	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) {
		std::cerr << "could not init SDL\n";
		return -1;
	}

	wm::manager wm_manager;
	wm_manager.create_window(screen_width, screen_height, SDL_WINDOW_OPENGL|(fullscreen ? SDL_WINDOW_FULLSCREEN : 0));
	if(g_main_window) {
		std::cerr << "could not set video mode\n";
		return -1;
	}

	{
	graphics::texture::manager texture_manager;
	font::manager font_manager;

	hex::terrain::init(wml::parse_wml_from_file("data/terrain.cfg"));
	framed_gui_element::init(wml::parse_wml_from_file("gui.cfg"));

	glShadeModel(GL_SMOOTH);
	glEnable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	play_game();
	}

	SDL_Quit();
}
